package com.demo.javaee.atomic;

import org.springframework.beans.factory.InitializingBean;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author shenguangyang
 */
public class N01_AtomicStampedReference {
    static AtomicReference<Integer> ar = new AtomicReference<>(5);
    static AtomicStampedReference<Integer> asr = new AtomicStampedReference<>(5,1);
    public static void main(String[] args) throws InterruptedException {
        System.out.println("================== ABA问题的产生 ==================");
        new Thread(() -> {
            ar.compareAndSet(5,100);
            ar.compareAndSet(100,5);
        },"t1").start();

        new Thread(() -> {
            try {
                // 睡眠3s保证t1线程完成ABA操作
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(ar.compareAndSet(5, 2020) + "\t" + ar.get());
        },"t2").start();

        TimeUnit.SECONDS.sleep(5);
        System.out.println("================== ABA问题的解决 ==================");


        new Thread(() -> {
            int stamp = asr.getStamp();
            System.out.println(Thread.currentThread().getName() + " 第1次版本号 = " + stamp);
            try {
                // 睡眠1s保证t4线程，获取到第一次版本号
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            asr.compareAndSet(5,100, asr.getStamp(), asr.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + " 第2次版本号 = " + asr.getStamp());
            asr.compareAndSet(100,5, asr.getStamp(), asr.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + " 第3次版本号 = " + asr.getStamp());
        },"t3").start();

        new Thread(() -> {
            int stamp = asr.getStamp();
            System.out.println(Thread.currentThread().getName() + " 第1次版本号 = " + stamp);
            try {
                // 睡眠3s保证t3线程完成ABA操作
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean success = asr.compareAndSet(5, 2020, stamp, stamp + 1);
            System.out.println(Thread.currentThread().getName() + "\t是否修该成功" + success + "\t最终值 = " + asr.getReference());
        },"t4").start();
    }
}
